import tkinter as tk
from tkinter import ttk, filedialog, messagebox
import threading
import os
import sys
from video_processor import VideoProcessor
from audio_processor import AudioProcessor
from metadata_handler import MetadataHandler
from config import Config


class VideoDeduplicationGUI:
    def __init__(self, root):
        self.root = root
        self.root.title("视频去重工具")
        self.root.geometry("1200x900")

        # 加载配置
        self.config = Config()

        # 创建主框架
        self.create_widgets()

    def create_widgets(self):
        # 文件选择框架
        file_frame = ttk.LabelFrame(self.root, text="文件选择", padding=10)
        file_frame.pack(fill="x", padx=10, pady=5)

        # 输入文件
        ttk.Label(file_frame, text="输入文件:").grid(row=0, column=0, sticky="w")
        self.input_var = tk.StringVar(value="/Users/wubenfei/PycharmProjects/video-deduplication-project/10s.mp4")
        self.input_entry = ttk.Entry(file_frame, textvariable=self.input_var, width=50)
        self.input_entry.grid(row=0, column=1, padx=5)
        ttk.Button(file_frame, text="浏览", command=self.browse_input).grid(row=0, column=2)

        # 输出文件
        ttk.Label(file_frame, text="输出文件:").grid(row=1, column=0, sticky="w")
        self.output_var = tk.StringVar(value="/Users/wubenfei/PycharmProjects/video-deduplication-project/output.mp4")
        self.output_entry = ttk.Entry(file_frame, textvariable=self.output_var, width=50)
        self.output_entry.grid(row=1, column=1, padx=5)
        ttk.Button(file_frame, text="浏览", command=self.browse_output).grid(row=1, column=2)

        # 参数配置框架
        param_frame = ttk.LabelFrame(self.root, text="参数配置", padding=10)
        param_frame.pack(fill="both", expand=True, padx=10, pady=5)

        # 创建参数控制
        self.create_param_controls(param_frame)

        # 按钮框架
        button_frame = ttk.Frame(self.root)
        button_frame.pack(fill="x", padx=10, pady=10)

        ttk.Button(button_frame, text="保存配置", command=self.save_config).pack(side="left", padx=5)
        ttk.Button(button_frame, text="加载配置", command=self.load_config).pack(side="left", padx=5)
        ttk.Button(button_frame, text="开始处理", command=self.start_processing).pack(side="right", padx=5)

        # 进度条
        self.progress = ttk.Progressbar(self.root, mode='indeterminate')
        self.progress.pack(fill="x", padx=10, pady=5)

        # 日志显示
        log_frame = ttk.LabelFrame(self.root, text="处理日志", padding=10)
        log_frame.pack(fill="both", expand=True, padx=10, pady=5)

        self.log_text = tk.Text(log_frame, height=10, width=80)
        scrollbar = ttk.Scrollbar(log_frame, orient="vertical", command=self.log_text.yview)
        self.log_text.configure(yscrollcommand=scrollbar.set)

        self.log_text.pack(side="left", fill="both", expand=True)
        scrollbar.pack(side="right", fill="y")

    def create_param_controls(self, parent):
        # 创建滚动区域
        canvas = tk.Canvas(parent)
        scrollbar = ttk.Scrollbar(parent, orient="vertical", command=canvas.yview)
        scrollable_frame = ttk.Frame(canvas)

        scrollable_frame.bind(
            "<Configure>",
            lambda e: canvas.configure(scrollregion=canvas.bbox("all"))
        )

        canvas.create_window((0, 0), window=scrollable_frame, anchor="nw")
        canvas.configure(yscrollcommand=scrollbar.set)

        # 视频参数
        video_frame = ttk.LabelFrame(scrollable_frame, text="视频参数", padding=5)
        video_frame.pack(fill="x", pady=5)

        self.create_slider(video_frame, "帧丢弃率", "frame_drop_rate", 0.0, 0.2, 0.01)
        self.create_slider(video_frame, "旋转角度范围", "rotation_range", 1.1, 1.4, 0.1)
        self.create_range_entry(video_frame, "缩放范围", "scale_range")
        self.create_range_entry(video_frame, "亮度范围", "brightness_range")
        self.create_range_entry(video_frame, "饱和度范围", "saturation_range")

        # 音频参数
        audio_frame = ttk.LabelFrame(scrollable_frame, text="音频参数", padding=5)
        audio_frame.pack(fill="x", pady=5)

        self.create_range_entry(audio_frame, "音高范围", "pitch_factor_range")
        self.create_range_entry(audio_frame, "速度范围", "speed_factor_range")
        self.create_slider(audio_frame, "噪声强度", "noise_intensity", 0.0, 0.1, 0.01)
        self.create_slider(audio_frame, "采样率", "sample_rate", 8000, 48000, 1000)
        self.create_slider(audio_frame, "掩码宽度(ms)", "mask_width_ms", 10, 500, 10)
        self.create_slider(audio_frame, "掩码间隔(s)", "mask_interval_s", 0.5, 5.0, 0.1)
        self.create_range_entry(audio_frame, "掩码强度范围", "mask_intensity_range")
        self.create_range_entry(audio_frame, "低通截止频率", "lowpass_cutoff_range")
        self.create_slider(audio_frame, "低通滤波器阶数", "lowpass_order", 1, 10, 1)

        canvas.pack(side="left", fill="both", expand=True)
        scrollbar.pack(side="right", fill="y")

    def create_slider(self, parent, label, param_name, min_val, max_val, step):
        frame = ttk.Frame(parent)
        frame.pack(fill="x", pady=2)

        ttk.Label(frame, text=label, width=15).pack(side="left")

        var = tk.DoubleVar(value=getattr(self.config, param_name))
        setattr(self, f"{param_name}_var", var)

        slider = ttk.Scale(frame, from_=min_val, to=max_val, variable=var,
                           orient="horizontal", command=lambda v: var.set(round(float(v), 2)))
        slider.pack(side="left", fill="x", expand=True, padx=5)

        value_label = ttk.Label(frame, textvariable=var, width=8)
        value_label.pack(side="right")

    def create_range_entry(self, parent, label, param_name):
        frame = ttk.Frame(parent)
        frame.pack(fill="x", pady=2)

        ttk.Label(frame, text=label, width=15).pack(side="left")

        range_val = getattr(self.config, param_name)
        min_var = tk.DoubleVar(value=range_val[0])
        max_var = tk.DoubleVar(value=range_val[1])

        setattr(self, f"{param_name}_min", min_var)
        setattr(self, f"{param_name}_max", max_var)

        ttk.Entry(frame, textvariable=min_var, width=8).pack(side="left", padx=2)
        ttk.Label(frame, text="到").pack(side="left")
        ttk.Entry(frame, textvariable=max_var, width=8).pack(side="left", padx=2)

    def browse_input(self):
        filename = filedialog.askopenfilename(
            title="选择输入视频文件",
            filetypes=[("视频文件", "*.mp4 *.avi *.mov *.mkv"), ("所有文件", "*.*")]
        )
        if filename:
            self.input_var.set(filename)

    def browse_output(self):
        filename = filedialog.asksaveasfilename(
            title="选择输出文件",
            defaultextension=".mp4",
            filetypes=[("MP4文件", "*.mp4"), ("所有文件", "*.*")]
        )
        if filename:
            self.output_var.set(filename)

    def save_config(self):
        self.update_config_from_ui()
        filename = filedialog.asksaveasfilename(
            title="保存配置",
            defaultextension=".json",
            filetypes=[("JSON文件", "*.json"), ("所有文件", "*.*")]
        )
        if filename:
            self.config.save(filename)
            messagebox.showinfo("成功", "配置已保存")

    def load_config(self):
        filename = filedialog.askopenfilename(
            title="加载配置",
            filetypes=[("JSON文件", "*.json"), ("所有文件", "*.*")]
        )
        if filename:
            self.config = Config.load(filename)
            self.update_ui_from_config()
            messagebox.showinfo("成功", "配置已加载")

    def update_config_from_ui(self):
        # 更新配置对象
        for attr in dir(self.config):
            if not attr.startswith('_') and hasattr(self, f"{attr}_var"):
                setattr(self.config, attr, getattr(self, f"{attr}_var").get())
            elif not attr.startswith('_') and hasattr(self, f"{attr}_min") and hasattr(self, f"{attr}_max"):
                min_val = getattr(self, f"{attr}_min").get()
                max_val = getattr(self, f"{attr}_max").get()
                setattr(self.config, attr, (min_val, max_val))

    def update_ui_from_config(self):
        # 更新UI显示
        for attr in dir(self.config):
            if not attr.startswith('_') and hasattr(self, f"{attr}_var"):
                getattr(self, f"{attr}_var").set(getattr(self.config, attr))
            elif not attr.startswith('_') and hasattr(self, f"{attr}_min") and hasattr(self, f"{attr}_max"):
                range_val = getattr(self.config, attr)
                getattr(self, f"{attr}_min").set(range_val[0])
                getattr(self, f"{attr}_max").set(range_val[1])

    def start_processing(self):
        if not self.input_var.get():
            messagebox.showerror("错误", "请选择输入文件")
            return

        if not self.output_var.get():
            messagebox.showerror("错误", "请选择输出文件")
            return

        self.update_config_from_ui()

        # 保存当前配置
        self.config.save()

        # 启动处理线程
        self.progress.start()
        thread = threading.Thread(target=self.process_video)
        thread.daemon = True
        thread.start()

    def process_video(self):
        """处理视频的后台线程"""
        try:
            # 获取文件路径
            input_file = self.input_var.get()
            output_file = self.output_var.get()

            if not input_file or not output_file:
                self.root.after(0, lambda: messagebox.showerror("错误", "请选择输入和输出文件"))
                return

            # 更新UI状态
            self.root.after(0, lambda: self.progress.start())

            # 处理视频
            temp_dir = None
            try:
                # 创建临时目录
                import tempfile
                temp_dir = tempfile.mkdtemp(prefix="video_dedup_")

                # 处理视频
                video_processor = VideoProcessor()
                video_temp = os.path.join(temp_dir, "video_temp.mp4")
                video_processor.process_video(input_file, video_temp)

                # 处理音频
                audio_processor = AudioProcessor()
                audio_temp = os.path.join(temp_dir, "audio_temp.wav")
                audio_processor.process_audio(input_file, audio_temp)

                # 合并视频和音频
                metadata_handler = MetadataHandler()
                final_temp = os.path.join(temp_dir, "final_temp.mp4")
                metadata_handler.merge_video_audio(video_temp, audio_temp, final_temp)

                # 修改元数据
                metadata_handler.modify_video_metadata(final_temp, output_file)

                # 完成处理
                self.root.after(0, lambda: messagebox.showinfo("成功", "处理完成！"))

            finally:
                # 清理临时文件
                if temp_dir and os.path.exists(temp_dir):
                    import shutil
                    shutil.rmtree(temp_dir)

        except Exception as e:
            error_msg = str(e)
            self.root.after(0, lambda msg=error_msg: messagebox.showerror("错误", f"处理失败：{msg}"))
        finally:
            self.root.after(0, lambda: self.progress.stop())


if __name__ == "__main__":
    root = tk.Tk()
    app = VideoDeduplicationGUI(root)
    root.mainloop()
